﻿using System.IO;
using System;

using InputFileGenerator;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace InputFileGeneratorTest
{
    
    
    /// <summary>
    ///This is a test class for ProgramTest and is intended
    ///to contain all ProgramTest Unit Tests
    ///</summary>
    [TestClass()]
    public class FiniteStateMachineFileCreationTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private const int acceptableError = 100;
        private const int acceptablePatternError = 10;
        //                               {0}        {1}                  {2}                                    {3}                                              {4}      {5}           {6}        {7}          {8}                                            {9}       
        private string[] smallArgs = { "-name", "finitestatemachine", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\smallContent.txt", "-size", "102400", "-patternsize", "10", "-dictionarypath", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\dictionary.txt" };
        private string[] mediumArgs = { "-name", "finitestatemachine", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\mediumContent.txt", "-size", "409600", "-patternsize", "15", "-dictionarypath", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\dictionary.txt" };
        private string[] largeArgs = { "-name", "finitestatemachine", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\largeContent.txt", "-size", "2048000", "-patternsize", "20", "-dictionarypath", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\dictionary.txt" };

        private bool IsFileCareful(string[] args)
        {
            if (!File.Exists(args[3]))
            {
                return false;
            }
            else
            {
                return IsSizeCareful(args);
            }
        }

        private bool IsSizeCareful(string[] args)
        {
            //fix: have a single return site
            bool returnval = true;
            long expectedSize = int.Parse(args[5]) * 1024;
            FileStream stream = null;          
            try
            {
                stream = new FileStream(args[3], FileMode.Open, FileAccess.Read, FileShare.Read);
                long contentSize = stream.Length;
                if ((contentSize > expectedSize - acceptableError) && contentSize < (expectedSize + acceptableError))
                {
                    //fix: have a single return site
                    //return IsPatternCareful(new StreamReader(stream), args);
                    returnval = IsPatternCareful(new StreamReader(stream), args);
                }
                else
                {
                    //fix: have a single return site
                    //return false;
                    returnval = false;
                }
            }
            catch (Exception e)
            {
                //fix: have a single return site
                //return false;
                returnval = false;

                //fix: at least print a message
                Console.Out.WriteLine(e.Message);
            }
            finally
            {
                stream.Close();
            }
            //fix: have a single return site
            return returnval;
        }

        private bool IsPatternCareful(StreamReader reader, string[] args)
        {
            int expectedSize = int.Parse(args[7]);
            int patternSize = 0;
            while (reader.Read() != 1 && ! reader.EndOfStream)
            {
                patternSize++;
            }
            if ((patternSize > expectedSize - acceptablePatternError) && patternSize < (expectedSize + acceptablePatternError))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        ///A test for Main
        ///</summary>
        [TestMethod()]
        [DeploymentItem("InputFileGenerator.exe")]
        public void MainTest()
        {
            //string[] args = mediumArgs;
            string[] args = smallArgs;
            //string[] args = largeArgs;

            Boolean exist = File.Exists(args[3]);
            Program_Accessor.Main(args);
            Assert.IsTrue(exist || IsFileCareful(args));
        }
    }
}
